package com.jian.utils;

import org.apache.catalina.User;
import org.springframework.data.redis.core.BoundValueOperations;
import org.springframework.data.redis.core.RedisTemplate;

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.LinkedHashMap;
import java.util.concurrent.TimeUnit;

/**
 * redis工具类
 *
 * @author 太难了
 */
public class RedisToken {

    /**
     * 保存一个redis数据 默认1小时ttl
     *
     * @param redisTemplate redis方法的类
     * @param key           token
     * @param value         value
     * @return 是否保存成功
     */
    public static boolean saveToRedis(RedisTemplate redisTemplate, String key, Object value) {
        BoundValueOperations valueOps = redisTemplate.boundValueOps(key);
        return Boolean.TRUE.equals(valueOps.setIfAbsent(value, 1, TimeUnit.HOURS));
    }

    /**
     * 保存一个redis数据 默认1小时ttl
     *
     * @param redisTemplate redis方法的类
     * @param key           token
     * @param value         value
     * @param timeOut       超时的时间
     * @param timeUnit      时间的单位
     * @return 是否保存成功
     */
    public static boolean saveToRedis(RedisTemplate redisTemplate,
                                      String key,
                                      Object value,
                                      Long timeOut,
                                      TimeUnit timeUnit) {
        BoundValueOperations valueOps = redisTemplate.boundValueOps(key);
        return Boolean.TRUE.equals(valueOps.setIfAbsent(value, timeOut, timeUnit));
    }


    /**
     * 封装一个redis的获取请求 返回一个LinkedHashMap对象
     *
     * @param redisTemplate redis方法的类
     * @param key           请求的key
     * @param timeOut       超时的时间
     * @param timeUnit      时间的单位
     * @return 返回一个LinkedHashMap对象
     */
    public static LinkedHashMap readFromRedis(RedisTemplate redisTemplate,
                                              String key,
                                              Long timeOut,
                                              TimeUnit timeUnit) {
        BoundValueOperations valueOps = redisTemplate.boundValueOps(key);
        LinkedHashMap map = (LinkedHashMap) valueOps.get();
        valueOps.expire(timeOut, timeUnit);
        return map;
    }

    /**
     * 封装一个redis的获取请求 返回一个LinkedHashMap对象
     *
     * @param redisTemplate redis方法的类
     * @param key           请求的key
     * @return 返回一个LinkedHashMap对象
     */
    public static LinkedHashMap readFromRedis(RedisTemplate redisTemplate,
                                              String key) {
        return readFromRedis(redisTemplate, key, 1L, TimeUnit.HOURS);
    }

    /**
     * 封装一个redis的获取请求 返回一个T泛型对象
     *
     * @param redisTemplate redis方法的类
     * @param key           请求的key
     * @param type          请求的value的类型
     * @param <T>           类的泛型
     * @return 返回从redis中读取值, 并封装为一个对象
     */
    public static <T> T readFromRedis(RedisTemplate redisTemplate, String key, Class<T> type) {
        return readFromRedis(redisTemplate, key, 1L, TimeUnit.HOURS, type);
    }

    /**
     * 封装一个redis的获取请求 返回一个T泛型对象
     *
     * @param redisTemplate redis方法的类
     * @param key           请求的key
     * @param timeOut       超时的时间
     * @param timeUnit      时间的单位
     * @param type          请求的value的类型
     * @param <T>           类的泛型
     * @return 返回从redis中读取值, 并封装为一个对象
     */
    public static <T> T readFromRedis(RedisTemplate redisTemplate,
                                      String key,
                                      Long timeOut,
                                      TimeUnit timeUnit,
                                      Class<T> type) {

        BoundValueOperations valueOps = redisTemplate.boundValueOps(key);
        LinkedHashMap map = (LinkedHashMap) valueOps.get();

        valueOps.expire(timeOut, timeUnit);
        T result;
        try {
            result = type.newInstance();
            Field[] fields = type.getDeclaredFields();
            for (Field field : fields) {
                if (Modifier.isFinal(field.getModifiers())
                        || Modifier.isStatic(field.getModifiers())) continue;
                field.setAccessible(true);
                Object o1 = map.get(field.getName());
                field.set(result, o1);
            }
        } catch (InstantiationException | IllegalAccessException e) {
            throw new RuntimeException(e);
        }
        return result;
    }

    /**
     * 删除redis一个key
     *
     * @param redisTemplate redis类的模板
     * @param token         key
     */
    public static void delFromToken(RedisTemplate redisTemplate, String token) {
        redisTemplate.delete(token);
    }
}
